package com.niiwoo.civet.user.service.local;

import com.niiwoo.civet.user.dao.entity.PortraitStatistics;
import com.niiwoo.civet.user.dao.mapper.PortraitStatisticsMapperExt;
import com.niiwoo.civet.user.enums.PortraitChannelEnum;
import com.niiwoo.civet.user.enums.PortraitCompareTypeEnum;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import java.util.Date;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 肖像认证统计本地服务
 */
@Service
public class PortraitStatisticsService {

    @Autowired
    PortraitStatisticsMapperExt portraitStatisticsMapper;

    @Autowired
    SnowflakeIdWorker snowflakeIdWorker;

    /**
     * 增加成功次数
     *
     * @param channel 肖像认证通道
     * @param compareType 对比类型
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public boolean incrSuccessTimes(PortraitChannelEnum channel, PortraitCompareTypeEnum compareType) {
        return incrTimes(channel, compareType, 1, 0, 0);
    }

    /**
     * 增加失败次数
     *
     * @param channel 肖像认证通道
     * @param compareType 对比类型
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public boolean incrFailTimes(PortraitChannelEnum channel, PortraitCompareTypeEnum compareType) {
        return incrTimes(channel, compareType, 0, 1, 0);
    }

    /**
     * 增加异常次数
     *
     * @param channel 肖像认证通道
     * @param compareType 对比类型
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public boolean incrExceptionTimes(PortraitChannelEnum channel, PortraitCompareTypeEnum compareType) {
        return incrTimes(channel, compareType, 0, 0, 1);
    }

    /**
     * @param channel 肖像认证通道
     * @param compareType 对比类型
     * @param success 成功次数
     * @param fail 失败次数
     * @param exception 异常次数
     */
    private boolean incrTimes(PortraitChannelEnum channel, PortraitCompareTypeEnum compareType, final int success, int fail, final int exception) {
        final Date now = new Date();
        return Optional.ofNullable(getByChannelAndTypeAndDate(channel, compareType, now))
                .map(ps -> {
                    PortraitStatistics statistics = new PortraitStatistics();
                    statistics.setId(ps.getId());
                    statistics.setSuccessTimes(success);
                    statistics.setFailTimes(fail);
                    statistics.setExceptionTimes(exception);
                    return portraitStatisticsMapper.incrTiemsById(statistics) > 0;
                })
                .orElseGet(() -> {
                    PortraitStatistics statistics = new PortraitStatistics();
                    statistics.setId(snowflakeIdWorker.nextId());
                    statistics.setChannel(channel.getValue());
                    statistics.setCompareType(compareType.getValue());
                    statistics.setSuccessTimes(success);
                    statistics.setFailTimes(fail);
                    statistics.setExceptionTimes(exception);
                    statistics.setStatisticalDate(now);
                    statistics.setCreateTime(now);
                    return portraitStatisticsMapper.insertSelective(statistics) > 0;
                });
    }

    /**
     * 获取统计记录
     * @param channel 渠道
     * @param compareType 对比类型
     * @param date 日期
     * @return
     */
    public PortraitStatistics getByChannelAndTypeAndDate(PortraitChannelEnum channel, PortraitCompareTypeEnum compareType, Date date) {
        return portraitStatisticsMapper.selectByChannelAndTypeAndDate(channel.getValue(), compareType.getValue(), date);
    }

}
